package wiiusej.apptest.activityTasks;

import java.sql.Timestamp;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import wiiusej.Wiimote;



public class SpellGameTask implements Runnable{

	//mode change freq
	private final long gameChangeFreq = 25000; //30 seconds
	
	private Timestamp lastTime;
	
	//current mode
	private Vector<Integer> allGameModes = new Vector<Integer>();
	private int gameMode = 0;
	
	//queue
	private BlockingQueue<Integer> fromRealTime;
	private BlockingQueue<Integer> toEnergy;
	private BlockingQueue<Integer> toRumbleQ;
	private ConcurrentLinkedQueue<Integer> fromEnergyQ;
	
	//motion types
	private final int SLOW_MOTION = 0;
	private final int BIG_SOFT = 1;
	private final int ROBOTIC = 2;
	private final int REST = 3;
	
	//GAME STATE
	private int gameState = 1;
		
	//logger
	Logger fileLogger;
	
	private Wiimote myWiimote;
	
	public SpellGameTask(BlockingQueue<Integer> fromRealTime, BlockingQueue<Integer> toEnergy, 
			BlockingQueue<Integer> toRumbleQ, ConcurrentLinkedQueue<Integer> fromEnergy, 
			Wiimote myWiimote){
		
		this.fromRealTime = fromRealTime;
		this.fromEnergyQ = fromEnergy;
		
		this.toEnergy = toEnergy;
		this.toRumbleQ = toRumbleQ;
		this.myWiimote = myWiimote;
		PropertyConfigurator.configure("log4j.properties");
		this.fileLogger = Logger.getLogger("gameController");
		
		initGameModes();	
		
		this.lastTime = new Timestamp(System.currentTimeMillis());
		
	}
	
	private void initGameModes() {
		allGameModes.add(0);
		allGameModes.add(1);
		allGameModes.add(2);
		
		fileLogger.info("*** GAME MODES: " + allGameModes);
			
		//uploadGameMode();		
		
	}
	

	@Override
	public void run() {


		while(true){
			
			
			//remove all part elements of the queue for avoiding delays
			if(!fromRealTime.isEmpty()){
				fromRealTime.clear();
			}	
			
			try {				
				//non-blocking queue
				Integer gameState = fromEnergyQ.poll();
				
				processState(gameState);								
				
				//blocking queue
				Integer motionType = fromRealTime.take();
				
				Timestamp t1 = new Timestamp(System.currentTimeMillis());
				
				fileLogger.info("$$$ Received Command: " + motionType +
						" ELAPSED_TIME: " + 
						(t1.getTime() - lastTime.getTime()));
				
				checkTime(t1);
				
				processCommand(motionType);
				
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
		
	}
	
	private void processState(Integer newState) {
		int i = 0;
		
		//fileLogger.info("$$$ Processing State - Current State: " + gameState);
		
		if(newState != null){
			uploadState(newState);
		}
		
		while(gameState == 0){			
			//non-blocking queue
			Integer gameState = fromEnergyQ.poll();
			
			if(gameState != null){
				uploadState(gameState);
			}
		}
		
		
		
		//remove all part elements of the queue for avoiding delays
		if(!fromRealTime.isEmpty()){
			fromRealTime.clear();
		}	
		
		
	}
	
	private void uploadState(Integer newState){

		if(gameState != newState){
			fileLogger.info("$$$ Updating Game State - From: " + gameState + 
					" To: " + newState);
			
			gameState = newState;			
		}else{
			fileLogger.info("$$$ Same State: " + gameState);
		}
		
	}

	private String nameGameMode(){
		
		switch(gameMode){
		
		case 0: 
			return "SLOW MOTION"; 
		case 1: 
			return "BIG&SOFT MOTION";
		case 2: 
			return "ROBOTIC MOTION";
		case 3: 
			return "RESTING";
		
		}	
		
		return null;
		
	}
	private void checkTime(Timestamp t1) {
		
		if( (t1.getTime() - lastTime.getTime()) >=  gameChangeFreq){
			lastTime = t1;
			fileLogger.info("*** UPLOADING GAME MODE - OLD GAME-MODE: " + gameMode);
			uploadGameMode();		
		}
		
		
	}

	private void uploadGameMode(){
		
		gameMode++;
		
		if(gameMode > 2){
			gameMode = 0;			
		}
		
		/*
		Random randomGenerator = new Random(System.currentTimeMillis());	
		boolean changed = false;
		
		while(!changed){
		
			int newMode = randomGenerator.nextInt(allGameModes.size()); 
			
			if(gameMode != newMode){
				gameMode = newMode;
				changed = true;			
			}else{
				changed = false;				
			}			
		}*/
		
		fileLogger.info("");
		fileLogger.info("****************************************");
		fileLogger.info("*** NEW GAME-MODE: " + nameGameMode());
		fileLogger.info("****************************************");
		fileLogger.info("");
		
		
	}
	
	private void processCommand(Integer command){
		
		//fileLogger.info("*** GAME-MODE: " + gameMode + " MOTION-TYPE: " + command);
		
		if(gameMode == command){
			fileLogger.info("SENDING ENERGY");
			toRumbleQ.add(1);			
			toEnergy.add(1);			
			fileLogger.info("");
		}else{
			toRumbleQ.add(0);
			fileLogger.info("TRY AGAIN");
			fileLogger.info("");
		}
		
		
	}
	
	private void rumble(Integer command){
		
		//fileLogger.info("<<<<<<<VIBRATING>>>>>>>>");
		
		if(command == BIG_SOFT || command == ROBOTIC){
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			myWiimote.activateRumble();
			
			try {
				//we could receive and update
				Thread.sleep(75);
				//command = fromEnergyAndRealQ.poll(75, TimeUnit.MILLISECONDS);
				//CheckCommand(command);						
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
			
			myWiimote.deactivateRumble();
			
			myWiimote.activateRumble();
			
			try {
				//we could receive and update
				Thread.sleep(75);
				//command = fromEnergyAndRealQ.poll(75, TimeUnit.MILLISECONDS);
				//CheckCommand(command);						
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}			
			myWiimote.deactivateRumble();
			
			
			
			
			
		}
		
		if(command == SLOW_MOTION){
			
			myWiimote.activateRumble();
			
			try {
				//we could receive and update
				Thread.sleep(150);
				//command = fromEnergyAndRealQ.poll(75, TimeUnit.MILLISECONDS);
				//CheckCommand(command);						
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			myWiimote.deactivateRumble();
			
			
		}
			
		
			
		
		
	}

}
